<?php

namespace app\socket\controller;

use app\common\CacheKey;
use app\service\Mt5;
use app\service\Redis;
use Workerman\Worker;
use Workerman\Connection\AsyncTcpConnection;

class Server
{
    public function start()
    {
        $worker = new Worker();
        $worker->onWorkerStart = function ($worker) {
            $token = (new Mt5())->Login();
            comLog('workerman', '测试1...');
            $url = config('mt5_ws') . "v1/streaming?access_token={$token}";
            $con = new AsyncTcpConnection($url);
            // 发送请求
            $con->onConnect = function ($con) {
                $data = json_encode([
                    'id' => config('mt5_account'),
                    'topic' => 1,
                    'action' => 11,
                ]);
                $con->send($data);
                comLog('workerman', '测试2...');
            };

            // 当服务端推送数据的时候可以在此回调函数里接收到
            $con->onMessage = function ($con, $data) {
                $redis = new Redis(['select' => 5]);
                $redis = $redis->handler();
                $data = json_decode($data, true);
                if (isset($data['data'])) {
                    $data = $data['data'];
                    $symbol = config('mt5_product');
                    foreach ($data as $v) {
                        if (in_array($v['symbol'], [$symbol[1], $symbol[2]])) {
                            $list = [
                                'price' => 0,
                                'ask' => $v['ask'],
                                'bid' => $v['bid'],
                                'symbol' => $v['symbol'],
                                'add_time' => time(),
                            ];
                            $redis->rpush(CacheKey::MT5_SINGLE, json_encode($list));
                            // 获取美原油数据
                            if ($v['symbol'] == $symbol[1]) {
                                $key = sprintf(CacheKey::MT5_REAL_SINGLE, 'USO');
                                $key1 = CacheKey::MT5_REAL_TIME;
                                $key2 = CacheKey::MT5_SINGLE_ORDER;
                            } else {
                                // 获取BTC数据
                                $key = sprintf(CacheKey::MT5_REAL_SINGLE, 'BTC');
                                $key1 = CacheKey::MT5_REAL_BTC_TIME;
                                $key2 = CacheKey::MT5_SINGLE_BTC_ORDER;
                            }
                            $redis->set($key, $v['ask']);
                            $redis->set($key1, time());
                            $redis->rpush($key2, json_encode($list));
                        }
                    }
                }
            };

            $con->onClose = function ($con) {
                // 这个是延迟断线重连，当服务端那边出现不确定因素，比如宕机，那么相对应的socket客户端这边也链接不上，那么可以吧1改成适当值，则会在多少秒内重新，我也是1，也就是断线1秒重新链接
                comLog('workerman', '测试3...');
                $redis = new Redis(['select' => 5]);
                $real_time = $redis->get(CacheKey::MT5_REAL_TIME);
                $diff_time = bcsub(time(), $real_time);
                if ($diff_time > 120) {
                    $con->close();
                    sleep(1);
                    $this->start();
                } else {
                    $con->reConnect(1);
                }
            };

            $con->onError = function ($con, $code, $msg) {
                // 异常错误
                $con->close();
                // 错误记录
                errorLog('workerman', "{$code}：{$msg}");
            };
            $con->connect();
        };

        Worker::runAll();
    }

    public function status()
    {
        return Worker::getStatus();
    }

    public function stop()
    {
        comLog('workerman', '正在执行关闭连接...');
        Worker::stopAll();
    }

}